package cn.sunxyz.code.operator;

import cn.sunxyz.code.original.Original;

import static cn.sunxyz.code.boolean_.BooleanAlgebra.*;

/**
 * Created by sunxyz on 2017/3/20.
 */
public class ADD implements Operator<boolean[]> {

    /***
     * 加法运算：
     * let a,b,c,s := [8]
     * a:0 + b:0 + c:0 => s:0,c:1 :> s:0;
     * a:1 + b:1 + c:1 => s:1,c:2 :> s:1;
     *    函数运算        运算结果    打印
     * */

    @Override
    public boolean[] operator(boolean[] bs1, boolean[] bs2) {
        return byteAdder(bs1, bs2);
    }

    //对老的实现方式进行的改进
    public boolean[] byteAdder(boolean[] x_s, boolean[] y_s) {
        if (x_s.length != 8) {
            throw new StackOverflowError("");
        }
        boolean[] oneByte = new boolean[8];
        boolean carry = false;
        for (int i = 7; i > -1; i--) {
            Original.HalfAdder halfAdder = Original.fullAdder(x_s[i], y_s[i], carry);
            carry = halfAdder.carry;
            oneByte[i] = halfAdder.sum;
        }
        return oneByte;
    }

    //老的实现方式
    public boolean[] byteOldAdder(boolean[] x_s, boolean[] y_s) {
        if (x_s.length != 8) {
            throw new StackOverflowError("");
        }
        Original.HalfAdder halfAdder7 = Original.fullAdder(x_s[7], y_s[7], false);
        Original.HalfAdder halfAdder6 = Original.fullAdder(x_s[6], y_s[6], halfAdder7.carry);
        Original.HalfAdder halfAdder5 = Original.fullAdder(x_s[5], y_s[5], halfAdder6.carry);
        Original.HalfAdder halfAdder4 = Original.fullAdder(x_s[4], y_s[4], halfAdder5.carry);
        Original.HalfAdder halfAdder3 = Original.fullAdder(x_s[3], y_s[3], halfAdder4.carry);
        Original.HalfAdder halfAdder2 = Original.fullAdder(x_s[2], y_s[2], halfAdder3.carry);
        Original.HalfAdder halfAdder1 = Original.fullAdder(x_s[1], y_s[1], halfAdder2.carry);
        Original.HalfAdder halfAdder0 = Original.fullAdder(x_s[0], y_s[0], halfAdder1.carry);
        boolean[] oneByte = new boolean[]{halfAdder0.sum, halfAdder1.sum, halfAdder2.sum, halfAdder3.sum, halfAdder4.sum, halfAdder5.sum, halfAdder6.sum, halfAdder7.sum};
        return oneByte;
    }

    //不引入加法器的方式
    public boolean[] old(boolean[] bs1, boolean[] bs2) {
        int len = bs1.length;
        if (len != bs2.length) {
            throw new RuntimeException("数据有误");
        }
        /**
         * let a,b,c = F;
         * @1: a = xor(x,y)； => 当前位运算 ;
         * @2: c = xor(a,b)； => 当前位结果;
         * @3: b = or(and(x,y),or(and(x,b),and(y,b))； => 进位=>x,y,up_b中有两个T即可进位；or(and(x,y),or(and(x,up_b),and(y,up_b))
         * if（未取尽） loop： @1;
         * c = b
         */
        boolean result[] = new boolean[len + 1];
        boolean carry = false;//进位 ->b
        boolean operation = false;//运算 ->a
        boolean current = false;//当前位 ->c
        for (int i = len - 1; i > -1; i--) {
            boolean x = bs1[i];
            boolean y = bs2[i];
            operation = xor(x, y);
            current = xor(operation, carry);
            //    System.out.println("x:= " + x + " y:= " + y + " curent := " + current + " 运算：= " + operation + " 是否进位" + carry);
            carry = or(and(x, y), and(xor(x, y), carry));
            //and(x, y) ? and(x, y) ：and(xor(x, y), carry)
            //or(and(x,y),or(and(x,carry),and(y,carry))
            result[i + 1] = current;
        }
        result[0] = carry;
        return result;
    }
}
